/*
 * BluePadServer.java
 *
 * Created on 24 marzo 2007, 16.44
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.bloomingstars.bluepad.server;

import com.bloomingstars.bluepad.comm.CommandCode;
import com.bloomingstars.bluepad.comm.DA2Protocol;
import com.bloomingstars.bluepad.util.BTUtils;
import java.io.InputStream;
import java.io.OutputStream;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;

/**
 *
 * @author vega
 */
public class BluePadServer implements Runnable
{
    public final static UUID uuid = new UUID("102030405060708090A0B0C0D0E0F010", false);
        
    /** Creates a new instance of BluePadServer */
    public BluePadServer()
    {
    }
    
    public InitStatus initialize()
    {
        try
        {
            device = LocalDevice.getLocalDevice();
        }
        catch (BluetoothStateException btse)
        {
            return InitStatus.INIT_LOCAL_DEVICE_ERROR;
        }
        
        try
        {
            device.setDiscoverable(DiscoveryAgent.GIAC);
            System.out.println("BT address: " + device.getBluetoothAddress());
            System.out.println("BT name: " + device.getFriendlyName());            
        }
        catch (BluetoothStateException btse)
        {
            return InitStatus.INIT_DISCOVERABLE_ERROR;
        }
        
        return InitStatus.INIT_OK;
    }
    
    public void run()
    {
        StreamConnection conn = null;
        String url = "btspp://localhost:" + new UUID(0x0003) + ";name=DA2_Emulator";
        System.out.println("Server URL:" + url);
        
        try
        {
            scn = (StreamConnectionNotifier) Connector.open(url);
            
            // Retrieve the service record template
            ServiceRecord rec = device.getRecord( scn );

            // set ServiceRecrod ServiceAvailability (0x0008) attribute to indicate our service is available
            // 0xFF indicate fully available status
            // This operation is optional
            // rec.setAttributeValue( 0x0008, new DataElement( DataElement.U_INT_1, 0xFF ) );

            // Print the service record, which already contains
            // some default values
            BTUtils.printServiceRecord( rec );

            while (true)
            {
                cFlag = true;

                conn = scn.acceptAndOpen();

                reader = new MyReader(this, conn);
                reader.start();

                while (cFlag)
                {
                    try
                    {

                        // Wait for receivedString;
                        synchronized (semaphore)
                        {
                            semaphore.wait();
                        }

                        // cFlag is false, therefore end the cycle immediately
                        if (!cFlag)
                        {
                            break;
                        }
                        
                        int cmd = DA2Protocol.getCommandCode(receivedString);

                        System.out.println("Command received: " + receivedString);

                        if (cmd != CommandCode.NULL_COMMAND)
                        {
                            String response = manager.processCommand(cmd);

                            if (!response.equals(""))
                            {
                                try
                                {
                                    System.out.println("Response string: " + response);
                                    OutputStream os = conn.openOutputStream();
                                    os.write(response.getBytes());
                                    os.flush();
                                    os.close();
                                }
                                catch (Exception ex)
                                {
                                    ex.printStackTrace(System.err);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        ex.printStackTrace(System.err);
                        cFlag = false;
                    }
                }
                
            }
        }
        catch (Exception ex)
        {
            ex.printStackTrace(System.err);
        }
    }
    
    class MyReader extends Thread
    {
        public MyReader(BluePadServer server, StreamConnection conn)
        {
            this.server = server;
            this.conn = conn;
        }
        
        public void terminate()
        {
            continueFlag = false;
        }
        
        public void run()
        {
            while (continueFlag)
            {
                try
                {
                  InputStream in = conn.openInputStream();
                  char ch = '\150';

                  do
                  {
                      int b = in.read();
                      ch = (char) b;

                      buffer.append(ch);                 
                  }
                  while (ch != '#');

                  receivedString = buffer.toString();
                  
                  // Clean buffer
                  if (buffer.length() > 0)
                  {
                      buffer.delete(0, buffer.length());
                  }


                  synchronized (semaphore)
                  {                  
                      semaphore.notify();
                  }

                }
                catch (Exception ex)
                {
                    ex.printStackTrace(System.err);
                    continueFlag = false;
                    
                    // Notify and stop listening thread
                    cFlag = false;
                    synchronized (semaphore)
                    {                  
                        semaphore.notify();
                    }
                    
                }                
            }
            
        }
        
        private BluePadServer server;
        private StreamConnection conn;
        private StringBuffer buffer = new StringBuffer();
        private boolean continueFlag = true;
    }
    
    /** Data received from client */
    private String receivedString = "";
    /** Protocol I/O and status manager */
    private ProtocolManager manager = new ProtocolManager();
    /** Thread interruption flag */
    private boolean cFlag = true;
    
    private MyReader reader;
    private StreamConnectionNotifier scn;
    private LocalDevice device;
    private DiscoveryAgent agent;
    private Object semaphore = new Object();
}
